#include "CGifPicture.h"

#include <EIKENV.H>
#include <BITDEV.H>
#include <fbs.h>
#include <mdaimageconverter.h>
#include "CGifPicture.h"
#include "CImageHandler.h"
#include "MyTimer.h"

/////////////////////////////////////
// Animated Gif, 基于active,有时间
// weidongy 2005.12.7
/////////////////////////////////////
// ---------------------------------------------------------
// Constructor
// ---------------------------------------------------------
//
CGifPicture::CGifPicture(CCoeControl& aOwner)
	: iOwner(aOwner)
{
	iFrameIndex = 0;
	//
	iBackBitmap = NULL;
	iImageHandler = NULL;
	iFrameCount = 0;
	iTimer = NULL;

}

CGifPicture::~CGifPicture( )
{
	if(iBackBitmap)
		delete iBackBitmap;
	if(iImageHandler)
		delete iImageHandler;
		
	for(int i = 0; i < iFrames.Count(); i++)
	{
		GIFDATA* gifdata = iFrames[i];
		CFbsBitmap* bitmap = gifdata->iBitmap;
		CFbsBitmap* maskbitmap = gifdata->iMaskBitmap;		
		delete bitmap;
		delete maskbitmap;
		delete gifdata;
	}
	iFrames.Reset();
	
	if(iTimer)
	{
		iTimer->Cancel();
		delete iTimer;
	}	
}

void CGifPicture::DrawFrame(CBitmapContext& aGc, TRect& aClipRect)
{
	if(iBackBitmap == NULL)
		return;

//	//create new background bitmap
	TPoint target = aClipRect.iTl;

	TRect bitmapRect=aClipRect;
	aGc.Reset();
	aGc.SetClippingRect(aClipRect);
	
	int i = iFrameIndex;
	FreshBackground(iBackBitmap, i);
	TFrameInfo aFrameInfo = iFrames[i]->iFrameInfo;
	
	aGc.BitBlt(aClipRect.iTl, iBackBitmap);	
}

//CPicture的接口
void CGifPicture::Draw( CGraphicsContext& aGc,
						     const TPoint& aTopLeft,
						     const TRect& aClipRect,
						     MGraphicsDeviceMap* aMap ) const
{
	TRect bitmapRect=aMap->TwipsToPixels(TRect(TPoint(),iSizeInTwips));
	bitmapRect.Move(aTopLeft);
	aGc.Reset();
	aGc.SetClippingRect(aClipRect);
	aGc.DrawBitmap(bitmapRect, iBackBitmap);
	///aGc.DrawLine(TPoint(0,0), TPoint(10,10));
}

void CGifPicture::ExternalizeL( RWriteStream& /*aStream*/ ) const
{
}

//叠加新的帧到背景上，形成新的背景图片，到aBitmap上
void CGifPicture::FreshBackground(CFbsBitmap* aBitmap, int frameindex) const
{
	GIFDATA* gifdata = iFrames[frameindex];	
	TFrameInfo aFrameInfo = gifdata->iFrameInfo;
	CFbsBitmap* bitmap = gifdata->iBitmap;
	CFbsBitmap* iMaskBitmap = gifdata->iMaskBitmap;	
	

	//get the gc of this new bitmap
	CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(aBitmap);
	CFbsBitGc* bitmapGc;
	bitmapDevice->CreateContext(bitmapGc);

	bool bTransparent = (aFrameInfo.iFlags & TFrameInfo::ETransparencyPossible) != 0;		
	if(bTransparent){
		bitmapGc->BitBltMasked(aFrameInfo.iFrameCoordsInPixels.iTl, bitmap, TRect(bitmap->SizeInPixels()), iMaskBitmap, false);
	}
	else
		bitmapGc->BitBlt(aFrameInfo.iFrameCoordsInPixels.iTl, bitmap);

	//destroy
	delete bitmapDevice;
	delete bitmapGc;
}

void CGifPicture::GetOriginalSizeInTwips( TSize& aSize ) const
{
	aSize = iSizeInTwips;
}

void CGifPicture::GetSize( TSize& aSize )
{
	aSize = iSizeInPixel;
}

void CGifPicture::ImageOperationComplete(TInt aError)
{
	GIFDATA* gifdata = new GIFDATA;
	gifdata->iBitmap = new(ELeave) CFbsBitmap();
	gifdata->iMaskBitmap = new(ELeave) CFbsBitmap();	
	gifdata->iFrameInfo = iImageHandler->FrameInfo();
	//
	if(iFrames.Count() == 0)
	{
		gifdata->iFrameInfo.iFlags &= ~TFrameInfo::ETransparencyPossible;
		/*
		 * ani gif的每一帧的效果，都依赖于前一帧的图像。 
		 * 所以保存每一帧的图像，一共叠加。iBbackBitmap就是起这个作用
		 */		
		iBackBitmap = new(ELeave) CFbsBitmap();
		iImageHandler->CopyBitmap(iBackBitmap);
	}

	iFrames.Append(gifdata);

	iImageHandler->CopyBitmap(gifdata->iBitmap);	
	iImageHandler->CopyMaskBitmap(gifdata->iMaskBitmap);

	if(iFrames.Count() < iFrameCount)
		LoadFileL(iFileName, iFrames.Count());
	
	if(iTimer == NULL)
	{
	    iTimer = CMyTimer::NewL(this, 100);	
    	iTimer->m_interval = 0;
		iTimer->Activate();	
	}
}
	
TBool CGifPicture::LineBreakPossible( TUint /*aClass*/,
										   TBool /*aBeforePicture*/,
										   TBool /*aHaveSpaces*/ ) const
{
	return EFalse;
}

void CGifPicture::LoadFileL(const TDesC& aFileName, TInt aSelectedFrame)
{
	if(iImageHandler == NULL)
	{
		iImageHandler = new (ELeave) CImageHandler(CEikonEnv::Static()->FsSession());
		iImageHandler->SetCallback(this);
	}
	if(aSelectedFrame == 0)
	{
		iFileName.Copy(aFileName);
		iImageHandler->FastImageInfo(aFileName, iSizeInPixel);
		iFrameCount = iImageHandler->FrameCount();
//		TBuf<10> bb;
//		bb.Num(iFrameCount);
//		CEikonEnv::Static()->InfoMsg(bb);
	}
	
	iImageHandler->LoadFileL(aFileName, aSelectedFrame);
}

//确保在owner中的draw中，调用gif::DrawFrame.
void CGifPicture::OnTimer(CMyTimer* timer, int eventid, int extrapara)
{
	TFrameInfo aFrameInfo = iFrames[iFrameIndex]->iFrameInfo;
	iTimer->m_interval = I64INT(aFrameInfo.iDelay.Int64());
	
	//iOwner.DrawNow();//TRect(0,0,60,60));
	//
	iFrameIndex++;
	iFrameIndex = iFrameIndex%iFrameCount;
	if(iFrameIndex >= iFrames.Count())//也许还没有调出所有的帧
		iFrameIndex = iFrames.Count() - 1;
}

void CGifPicture::SetOriginalSizeInTwips( TSize aSize )
{
	iSizeInTwips = aSize;
}

